home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
CH_5.7
/
EH_SEG
/
EH_SEG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
14KB
|
578 lines
/*
* eh_seg.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* ** E(xtract) H(istograms)_SEG
* **
* ** routine to extract desired set of parameters from a data file of
* ** type .SEG whose name is entered as a command line argument and
* ** construct a histogram; write output file of type *.hdt to be read
* ** by routine hf.c
* **
*/
#include "eh_seg.h"
#define MAX_REC_SIZE 1200
#define BIN_NUMBER 10 /* no bins in histogram */
#define LEN_HIST "\nhistogram for segment length"
#define ANGLE_HIST "\nhistogram for segment turn angles"
#define ON 1
#define OFF 0
#undef SHOW_ANG
#undef SHOW_SORT
#define DBG_ANG
/*
* ** global variables
*/
extern char *optarg;
extern int optind, opterr;
static char *HIST_HEADER;
int N_BINS = BIN_NUMBER;
int MIN_SET = 0;
int MAX_SET = 0;
int WRITE_FILE = 0;
int SHOW_INPUT = 0;
int A_HIST = 0;
int L_HIST = 0;
/*
* usage of routine
*/
void
usage (char *progname)
{
progname = last_bs (progname);
printf ("USAGE: %s infile [-s] [-a] [-l] [-n n] [-i f] [-f f] [-w] [-L]\n", progname);
printf ("\n%s extracts histogram data from infile (SEG), generated by\n", progname);
printf ("fitpolyg, containing line segment data\n\n");
printf ("ARGUMENTS:\n");
printf (" infile: input filename (SEG)\n\n");
printf ("OPTIONS:\n");
printf (" -s: show input data\n\n");
printf (" construct histogram for:\n");
printf (" -a: turn angles between consecutive segments\n");
printf (" -l: histogram of segment lengths\n");
printf (" -n n: set number of bins to n (default: 10)\n");
printf (" -i f: set initial value to (float)f (default: MIN)\n");
printf (" -f f: set final value to (float)f (default: MAX)\n");
printf (" -w: write output file of type .hdt (hist data)\n");
exit (1);
}
/*
* ** comparison function for qsort():
* ** sort array of tuples in order of increassing x-values
*/
int
compare (t1, t2)
float *t1, *t2;
{
return ((int) SIGN (*t1 - *t2));
}
/*
* ** determine mean of input data set
*/
double
find_mean (float *data, int n)
{
int i;
double mean = 0.0;
for (i = 0; i < n; i++)
mean += *(data + i);
return (mean / (double) n);
}
/*
* ** determine standard deviation of input data set
*/
double
find_sigma (float *data, int n, double mean)
{
int i;
double xi, sigma = 0.0;
for (i = 0; i < n; i++) {
xi = (double) (*(data + i));
sigma += (xi - mean) * (xi - mean);
}
sigma /= (double) (n - 1);
return (sqrt (sigma));
}
/*
* ** construct histogram of input data
*/
void
construct_hist (int n, float *data, float *hist, double bw, double data_base)
{
int i, ibin;
for (i = 0; i < n; i++) {
if (*(data + i) != 0) {
ibin = 0;
while (*(data + i) >= data_base + ibin * bw)
ibin++;
*(hist + ibin - 1) += 1;
}
}
}
/*
* ** read first line in data file to determine size of record
*/
int
seg_size (FILE * file)
{
int retval;
int n_rec;
if (((retval = fscanf (file, "%d", &n_rec)) == 0) || (retval == EOF)) {
printf ("wrong input file format!\n");
exit (1);
}
return (n_rec);
}
#define LOLIM 0.01
#define UPLIM 200.0
/*
* ** decode given slope, tan PHI, and return signed angle PHI (in rad);
* ** sign convention: CCW <--> pos, counting from pos. x-direction
*/
double
slp_to_angle (double m, double delx, double dely)
{
double phi = -5.0;
#ifdef DEBUG
printf ("SLP_TO_ANGLE:...m = %lf, delx = %lf, dely = %lf\n",
m, delx, dely);
#endif
if (fabs (m) < LOLIM) { /* horizontal segm */
if (SIGN (delx) > 0)
phi = 0.0;
else if (SIGN (delx) < 0)
phi = PI;
else
phi = -7.0;
}
else if (fabs (m) > UPLIM) { /* vertical segm */
if (SIGN (dely) < 0)
phi = 0.5 * PI;
else if (SIGN (dely) > 0)
phi = 1.5 * PI;
else
phi = -8.0;
}
else {
if (SIGN (delx) > 0) {
if (SIGN (dely) > 0)
phi = atan (m);
if (SIGN (dely) < 0)
phi = 2.0 * PI + atan (m);
}
else if (SIGN (delx) < 0) {
if (SIGN (dely) > 0)
phi = PI + atan (m);
if (SIGN (dely) < 0)
phi = PI + atan (m);
}
else
phi = -9.0;
}
if (fabs (phi) > 2.0 * PI) {
printf ("\nSLP_TO_AN:...ill defined condition encountered:");
printf (" m = %lf, phi = %lf\n", m, phi);
phi = 0.0;
return (phi);
}
#ifdef DEBUG
printf (" value to be returned: %8.4lf\n", phi);
#endif
return (phi);
}
/*
* ** read segment data from formatted data file (generally of type .seg)
* ** written by pcctoseg.c; first column contains segment index: must not
* ** exceed 9999!!
*/
void
get_seg_data (fp, n_segm, segm)
FILE *fp;
int n_segm;
struct Segm *segm;
{
int i;
int retval;
for (i = 0; i < n_segm; i++) {
retval = fscanf (fp, "%4d %3d %3d %3d %3d %f %3d",
&((segm + i)->segm_ind),
&((segm + i)->ptO.x), &((segm + i)->ptO.y),
&((segm + i)->ptF.x), &((segm + i)->ptF.y),
&((segm + i)->slope), &((segm + i)->line_ind));
}
}
void
main (argc, argv)
int argc;
char *argv[];
{
int i_arg;
int i, ich, is;
int n_segm;
static char wbuf[20];
static char *inp_suffix =
{".seg"}; /* default inp file suffix */
static char *seg_type =
{".seg"}; /* suffix for .sgl inp file */
static char *wsuffix =
{".hdt"}; /* suffix for output file name */
char *rbuf;
int n_parms = 3;
double ndel_x, ndel_y, del_x, del_y;
struct Segm *inSegm; /* sample input */
int cur_ln_ind, next_ln_ind;
float cur_slp, next_slp;
double cur_th, next_th, del_th;
float bin_width, min = (float) -1.0, max = (float) -1.0;
float *data, *hist;
double mean, std_dev;
float one = (float) 1.0;
FILE *fpIn, *fpOut;
/*
* ** cmd line options:
*/
static char *optstring = "slan:i:f:wL";
/*
* ** parse command line
*/
optind = 2;
opterr = ON; /* give error messages */
if (argc < 2)
usage (argv[0]);
while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
switch (i_arg) {
case 's':
printf ("\n...option %c: ", i_arg);
printf ("display input data\n");
SHOW_INPUT = ON;
break;
case 'a':
printf ("\n...option %c: ", i_arg);
printf ("hist of turn angles betw consec segm\n");
A_HIST = ON;
break;
case 'l':
printf ("\n...option %c: ", i_arg);
printf ("hist of segm lengths\n");
L_HIST = ON;
break;
case 'n':
printf ("\n...option %c: ", i_arg);
printf ("set number of bins to %d\n",
N_BINS = atoi (optarg));
break;
case 'i':
printf ("\n...option %c: ", i_arg);
printf ("set min (init value) to %f\n",
min = (float) atof (optarg));
MIN_SET = 1;
break;
case 'f':
printf ("\n...option %c: ", i_arg);
printf ("set max (final value) to %f\n",
max = (float) atof (optarg));
MAX_SET = 1;
break;
case 'w':
printf ("\n...option %c: ", i_arg);
printf ("write output to file %s\n", wbuf);
WRITE_FILE = 1;
break;
case 'L':
print_sos_lic ();
exit (0);
default:
printf ("\n...unknown cmd line argument\n");
exit (1);
break;
}
}
printf ("read sgl data from file %s\n", rbuf = argv[1]);
/* open input file */
if ((fpIn = fopen (rbuf, "r")) == NULL) {
printf ("\n...cannot not open input file\n");
exit (1);
}
/* initialize size variables */
if ((n_segm = seg_size (fpIn)) > MAX_REC_SIZE) {
printf ("\n...record size of %d exceeds limit of %d\n",
n_segm, MAX_REC_SIZE);
exit (1);
}
/* construct output file name */
ich = 0;
while ((*(wbuf + ich) = *(rbuf + ich)) != '.')
ich++;
for (is = 0; is < 4; is++)
*(wbuf + (ich) + is) = *(wsuffix + is);
/* strip input file suffix */
for (is = 0; is < 4; is++)
*(inp_suffix + is) = *(rbuf + (ich) + is);
if (strcmp (inp_suffix, seg_type) != 0) {
printf ("\n...unknown input file type encountered:");
printf (" default: %s\n", seg_type);
fclose (fpIn);
exit (1);
}
if (WRITE_FILE) {
if ((fpOut = fopen (wbuf, "w")) == NULL) {
printf ("\n...cannot open %s for writing\n", wbuf);
exit (1);
}
}
if ((A_HIST == 0) && (L_HIST == 0)) {
printf ("\n...must specify option -a or -l!!\n");
exit (1);
}
if (A_HIST == 1) {
if (min > max) {
printf ("\n...delected min exceeds max!!\n");
exit (1);
}
}
printf ("...number of segments in file %s: %d\n", rbuf, n_segm);
/*
* ** allocate memory
*/
if ((hist = (float *) calloc ((size_t) N_BINS, sizeof (float))) == NULL) {
printf ("\nEH_SEG: mem alloc for hist failed\n");
exit (1);
}
if ((inSegm = (struct Segm *) calloc ((size_t) n_segm, sizeof (struct Segm))) == NULL) {
printf ("\nEH_SEG: mem alloc for inSegm failed\n");
exit (1);
}
if ((data = (float *) calloc ((size_t) n_segm, sizeof (float))) == NULL) {
printf ("\nEH_SEG: mem alloc for data failed\n");
exit (1);
}
/*
* ** fetch data
*/
get_seg_data (fpIn, n_segm, inSegm);
/*
* ** write output
*/
if (SHOW_INPUT == ON) {
printf ("\n...input data:\n");
for (i = 0; i < n_segm; i++) {
printf ("%4d %3d %3d %3d %3d %f8.2 %4d\n",
(inSegm + i)->segm_ind,
(inSegm + i)->ptO.x, (inSegm + i)->ptO.y,
(inSegm + i)->ptF.x, (inSegm + i)->ptF.y,
(inSegm + i)->slope, (inSegm + i)->line_ind);
}
}
/*
* ** evaluate statistics and construct histogram
*/
if (L_HIST == ON) {
printf ("\n...evaluating histogram of segment lengths...\n");
for (i = 0; i < n_segm; i++) {
del_x = (double) ((inSegm + i)->ptF.x - (inSegm + i)->ptO.x);
del_y = (double) ((inSegm + i)->ptF.y - (inSegm + i)->ptO.y);
*(data + i) = (float) sqrt (del_x * del_x + del_y * del_y);
}
}
else if (A_HIST == ON) {
printf ("\n...evaluating histogram of turn angles...\n");
i = 0;
do {
cur_ln_ind = (inSegm + i)->line_ind;
#ifdef SHOW_ANG
printf ("\nline_index: %4d\n", cur_ln_ind);
#endif
while ((next_ln_ind = (inSegm + i + 1)->line_ind) == cur_ln_ind) {
#ifdef SHOW_ANG
printf ("...segment pair:%4d %4d ",
(inSegm + i)->segm_ind, (inSegm + i + 1)->segm_ind);
#endif
cur_slp = (inSegm + i)->slope;
del_x = (double) ((inSegm + i)->ptF.x - (inSegm + i)->ptO.x);
del_y = (double) ((inSegm + i)->ptF.y - (inSegm + i)->ptO.y);
next_slp = (inSegm + i + 1)->slope;
ndel_x = (double) ((inSegm + i + 1)->ptF.x - (inSegm + i + 1)->ptO.x);
ndel_y = (double) ((inSegm + i + 1)->ptF.y - (inSegm + i + 1)->ptO.y);
/* angle conv: CCW <--> positive */
if (cur_slp * next_slp == -1.0) {
printf ("\n...segments perpendicular...\n");
if (cur_slp > 0.0) {
if (del_x > 0.0) {
if (ndel_x > 0.0)
*(data + i) = (float) 90.0;
if (ndel_x < 0.0)
*(data + i) = (float) -90.0;
}
else if (del_x < 0.0) {
if (ndel_x > 0.0)
*(data + i) = (float) -90.0;
if (ndel_x < 0.0)
*(data + i) = (float) 90.0;
}
}
else if (cur_slp < 0.0) {
if (del_x > 0.0) {
if (ndel_x > 0.0)
*(data + i) = (float) -90.0;
if (ndel_x < 0.0)
*(data + i) = (float) 90.0;
}
else if (del_x < 0.0) {
if (ndel_x > 0.0)
*(data + i) = (float) 90.0;
if (ndel_x < 0.0)
*(data + i) = (float) -90.0;
}
}
}
else {
cur_th = slp_to_angle (cur_slp, del_x, del_y);
next_th = slp_to_angle (next_slp, ndel_x, ndel_y);
del_th = next_th - cur_th;
#ifdef SHOW_ANG
printf (" th: %5.2lf nth: %5.2lf d_th: %5.2lf",
cur_th, next_th, del_th);
#endif
if (del_th > PI)
del_th = -(2.0 * PI - del_th);
if (del_th < -PI)
del_th = 2.0 * PI + del_th;
*(data + i) = (float) ((del_th * 180.0) / PI);
#ifdef SHOW_ANG
printf (" d_th(deg): %5.2f\n", *(data + i));
#endif
}
cur_ln_ind = next_ln_ind;
i++;
}
i++;
} while (i < n_segm);
}
printf ("\n...sorting and constructing histogram\n");
#if defined(LINUX)
qsort (data, n_segm, sizeof (float), (__compar_fn_t) compare);
#else
qsort (data, n_segm, sizeof (float), compare);
#endif
#ifdef SHOW_SORT
printf ("\n...sorted data:\n");
for (i_sgl = 0; i_sgl < n_segm; i_sgl++)
printf (" data[%d] = %f\n", i_sgl, *(data + i_sgl));
#endif
if (MIN_SET == 0)
min = *(data + 0);
if (MAX_SET == 0)
max = *(data + n_segm - 1);
mean = find_mean (data, n_segm);
std_dev = find_sigma (data, n_segm, mean);
bin_width = (max - min) / ((float) (N_BINS - 1));
construct_hist (n_segm, data, hist, bin_width, min);
printf ("\nhistogram:\n");
printf ("......mean: %lf\n", mean);
printf ("...std_dev: %lf\n", std_dev);
printf ("...min: %f, bin_width: %f, max: %f\n", min, bin_width, max);
for (i = 0; i < N_BINS; i++) {
printf (" %6.2f", *(hist + i));
if ((i + 1) % 10 == 0)
printf ("\n");
}
fclose (fpIn);
/*
* ** write output file of type .hdt (see also: .adt, .pdt)
*/
if (WRITE_FILE == 1) {
fprintf (fpOut, "%d\n", N_BINS);
for (i = 0; i < n_parms; i++)
fprintf (fpOut, "%f\n", one);
for (i = 0; i < N_BINS; i++)
fprintf (fpOut, "%f %f\n", (float) i, *(hist + i));
fclose (fpOut);
}
free (hist);
free (inSegm);
free (data);
}